package com.sanen.flyer.main;

import com.sanen.flyer.common.Constant;
import com.sanen.flyer.entity.Bullet;
import com.sanen.flyer.entity.GameBackground;
import com.sanen.flyer.entity.blast.Blast;
import com.sanen.flyer.entity.enemy.Enemy;
import com.sanen.flyer.entity.enemy.air1;
import com.sanen.flyer.entity.hero.Hero;
import com.sanen.flyer.factory.BgFactory;
import com.sanen.flyer.factory.BlastFactory;
import com.sanen.flyer.factory.EnemyFactory;
import com.sanen.flyer.factory.HeroFactory;
import com.sanen.flyer.listener.KeyListener;
import com.sanen.flyer.tool.Console;
import com.sanen.flyer.tool.ThreadTool;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wsse
 * @date 2018-09-05 10:00
 */
public class Game extends JPanel implements Runnable {
    public static final int REFRESH_INTERVAL = 1000 / 100;//每秒100针
    public static KeyListener keyListener;
    static Thread task;
    boolean isRunning = true;
    static JFrame frame;
    List<Bullet> enemyBullets;
    List<Bullet> heroBullets;
    GameBackground bg;
    Hero hero;
    List<Enemy> enemys;
    List<Blast> blasts;

    public static void main(String[] args) {
        Game game = new Game();
        game.init();
        // 创建窗体(画板)
        frame = new JFrame();
        // 设置窗体(画板)大小
        frame.setSize(Constant.getWindowWidth() + 16, Constant.getWindowHeight() + 38);
        // 设置窗体标题
        frame.setTitle("flyer");
        // 给画板添加一块画布,JPaner或其子类
        frame.add(game);
        // 设置其总在最上层,这样不会被其他程序挡住
        frame.setAlwaysOnTop(true);
        // 设置窗体可见(默认窗体是不可见的,所以需要我们设置成可见)
        frame.setVisible(true);
        // 设置窗体右上角关闭按钮功能为退出程序并关闭窗体
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        game.listener();
        task = new Thread(game);
        task.start();
    }

    public void init() {
        bg = BgFactory.getBg(BgFactory.BG_2);
        hero = HeroFactory.getHero(HeroFactory.HERO_HUAN_YING);
        enemys = new ArrayList<>();
        heroBullets=new ArrayList<>();
        blasts=new ArrayList<>();

    }

    /**
     * 工作线程
     */
    public void run() {
        while (isRunning) {
            long startTime = System.currentTimeMillis();
            logic();
            repaint();
            long endTime = System.currentTimeMillis();
            long runtime = endTime - startTime;
            if (REFRESH_INTERVAL - runtime>0)
            ThreadTool.sleep(REFRESH_INTERVAL - runtime);
        }
    }

    /**
     * 逻辑处理
     */
    int index = 0;

    private void logic() {
        bg.logic();
        hero.logic();
        index++;
        removeEnemy();
        removeBullet();
        removeBlast();
        if (index % 100 == 0) {
            enemys.add(EnemyFactory.getEnemy(1));
        }
        for (Enemy e:enemys){
           e.logic();
        }
        enemyByHitBullet();
        for (int i = 0; i < heroBullets.size(); i++) {
            heroBullets.get(i).logic();
        }
        for(Blast b:blasts){
            b.logic();
        }
        shoot();
    }



    /**
     * 绘图
     */
    protected void paintComponent(Graphics g) {
        bg.draw(g);

        //敌机
        for (int i=0;i<enemys.size();i++){
            enemys.get(i).draw(g);
        }
        //英雄子弹
        for (int i = 0; i < heroBullets.size(); i++) {
            heroBullets.get(i).draw(g);
        }
        //爆炸动画
        for (int i = 0; i <blasts.size(); i++) {
            blasts.get(i).draw(g);
        }
        //英雄机
        hero.draw(g);
    }

    /**
     * 处理飞机设计
     */
    private void shoot() {
        heroBullets.addAll(hero.shoot());
    }

    /**
     * 敌机与子弹碰撞
     */
    private void enemyByHitBullet(){
        for(Enemy e:enemys){
          for(Bullet b:heroBullets){
              if (e.byHit(b)){
                b.setRemove(true);
              }
          }
        }
    }

    /**
     * 移除待清除飞机,并生成飞机爆炸对象
     */
    private void removeEnemy(){
        for (int i = 0; i < enemys.size(); i++) {
            if(enemys.get(i).isRemove()){
                blasts.add(enemys.get(i).getBlast());
                enemys.remove(i);
                i--;
            }
        }
    }

    /**
     * 移除待清除子弹,并生成子弹爆炸对象
     */
    private void removeBullet(){
        for (int i = 0; i < heroBullets.size(); i++) {
            if(heroBullets.get(i).isRemove()){
                if (heroBullets.get(i).getBlast()!=null)
                blasts.add(heroBullets.get(i).getBlast());
                heroBullets.remove(i);
                i--;
            }
        }
    }
    /**
     * 移除待清除爆炸,并回收
     */
    private void removeBlast(){
        for (int i = 0; i < blasts.size(); i++) {
            if (blasts.get(i).isRemove()){
                BlastFactory.recycle(blasts.remove(i));
                i--;
            }
        }
    }
    /**
     * 监听处理
     */
    private void listener() {
        windowListener();
        mouseListener();
        keyListener();
    }

    /**
     * 键盘监听
     */
    private void keyListener() {
        //键盘监听
        keyListener = new KeyListener() {
            @Override
            public void keyPressed(int keyCode) {

            }
        };
        frame.addKeyListener(keyListener);
        frame.requestFocus();
    }

    /**
     * 游戏窗口监听
     */
    private void windowListener() {
        frame.addWindowFocusListener(new WindowFocusListener() {
            public void windowGainedFocus(WindowEvent e) {
            }

            //失去焦点
            public void windowLostFocus(WindowEvent e) {
                keyListener.clear();
            }
        });
    }

    /**
     * 鼠标移动点击监听
     */
    private void mouseListener() {
        MouseAdapter ma = new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

            }

            @Override
            public void mouseMoved(MouseEvent e) {
//                System.out.println(e.getX() + "," + e.getY());
            }
        };
        frame.addMouseListener(ma);
        frame.addMouseMotionListener(ma);
    }

    public static boolean isPress(String key) {
        return keyListener.isPress(key);
    }
}
